﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.ShprossesBuilder.Modelling.Components.Actions;
using ITAP.ShprossesBuilder.Modelling;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.ShprossesBuilder.Properties;
using ITAP.ShprossesBuilder.Editor;
using ITAP.Core.Calculations;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder.Operations
{
    public class OperationCreateDiamondByConnectorPosition : IOperation
    {
        #region IOperation Members

        public string Name
        {
            get { return "Создать ромб по позиции соединителя"; }
        }

        public OperationGroup OperationGroup
        {
            get { return OperationGroup.ShprossConnectorOperation; }
        }

        public System.Drawing.Image Thumbnail
        {
            get { return Resources.CreateDiamondByPosition.ToBitmap(); }
        }

        public void Execute(ModelControl modelControl)
        {
            List<ShprossConnector> mainConnectors = new List<ShprossConnector>();
            foreach (IComponent selectedComponent in modelControl.ModelContainer.SelectedComponentsStack)
            {
                if (selectedComponent is ShprossConnector)
                    mainConnectors.Add(selectedComponent as ShprossConnector);
            }

            if (mainConnectors.Count == 0)
                return;

            DiamondAlignmentForm diamondForm = new DiamondAlignmentForm(true, true);
            if (diamondForm.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;

            SelectMaterialForm connectorForm = new SelectMaterialForm();
            connectorForm.Initialize(modelControl.ProfileProvider, new Material[] { Material.ShprossConnector }, false, "Выберите горизонтальные соединители", false);
            if (connectorForm.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;

            ShprossConnector connectorPrototypeLeftRight = connectorForm.SelectedComponent as ShprossConnector;

            connectorForm.Initialize(modelControl.ProfileProvider, new Material[] { Material.ShprossConnector }, false, "Выберите вертикальные соединители", false);

            if (connectorForm.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;

            ShprossConnector connectorPrototypeUpDown = connectorForm.SelectedComponent as ShprossConnector;

            ShprossConnector right = connectorPrototypeLeftRight.Copy() as ShprossConnector;
            
        //    right.Angle = new Angle(-Math.PI / 2);
            right.SerialNumber = 0;
            
            ShprossConnector left = connectorPrototypeLeftRight.Copy() as ShprossConnector;
         //   left.Angle = new Angle(Math.PI / 2);
            //left.Rotate(Math.PI / 2);
            left.SerialNumber = 0;

            ShprossConnector up = connectorPrototypeUpDown.Copy() as ShprossConnector;
            up.SerialNumber = 0;

            ShprossConnector down = connectorPrototypeUpDown.Copy() as ShprossConnector;
           // down.Rotate(Math.PI);
          //  down.Angle = new Angle(Math.PI);
            down.SerialNumber = 0;

            Shpross shprossPrototype = null;
            if (diamondForm.FitProfiles)
            {
                SelectMaterialForm form = new SelectMaterialForm();
                form.Initialize(modelControl.ProfileProvider, new Material[] { Material.Shpross }, false, "Выберите профиль", false);
                if (form.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                    return;

                shprossPrototype = form.SelectedComponent as Shpross;
            }

            DiamondMeasure measure = diamondForm.DiamondAlignmentMeasure;
            double distance = diamondForm.Distance;

            foreach (ShprossConnector mainConnector in mainConnectors)
            {
                List<ShprossConnector> shprossConnectors = new List<ShprossConnector>();
                right.MoveTo(mainConnector.Position);
                up.MoveTo(mainConnector.Position);
                left.MoveTo(mainConnector.Position);
                down.MoveTo(mainConnector.Position);

                shprossConnectors.Add(right.Copy() as ShprossConnector);
                shprossConnectors.Add(up.Copy() as ShprossConnector);
                shprossConnectors.Add(left.Copy() as ShprossConnector);
                shprossConnectors.Add(down.Copy() as ShprossConnector);

                shprossConnectors[0].Angle = new Angle(-Math.PI / 2);
                shprossConnectors[1].Angle = new Angle(0);
                shprossConnectors[2].Angle = new Angle(Math.PI / 2);
                shprossConnectors[3].Angle = new Angle(Math.PI);

                //ModelPoint center = mainConnector.Position;

                Model parent = mainConnector.Parent as Model;

                List<IComponent> newComponents = new List<IComponent>();
                switch (measure)
                {
                    case DiamondMeasure.Width:
                        newComponents = this.WidthAlign(shprossConnectors, shprossPrototype, distance);
                        break;
                    case DiamondMeasure.Height:
                        newComponents = this.HeightAlign(shprossConnectors, shprossPrototype, distance);
                        break;
                    case DiamondMeasure.DiamondBorder:
                        newComponents = this.DiamondBorderAlign(shprossConnectors, shprossPrototype, distance);
                        break;
                }

                foreach (IComponent newComponent in newComponents)
                    parent.AddInnerComponent(newComponent);

                if(diamondForm.DeleteConnector)
                    parent.RemoveInnerComponent(mainConnector);
            }
        }

        public bool CanUndo
        {
            get { return true; }
        }

        #endregion

        private List<IComponent> GetShprosses(List<ShprossConnector> shprossConnectors, Shpross shprossPrototype)
        {
            List<IComponent> shprosses = new List<IComponent>();
            if (shprossPrototype != null)
            {
                Shpross rightUp = shprossPrototype.Copy() as Shpross;
                rightUp.SerialNumber = 0;
                rightUp.MoveStartPointTo(shprossConnectors[0][1].Position);
                rightUp.MoveEndPointTo(shprossConnectors[1][2].Position);

                Shpross upLeft = shprossPrototype.Copy() as Shpross;
                upLeft.SerialNumber = 0;
                upLeft.MoveStartPointTo(shprossConnectors[1][1].Position);
                upLeft.MoveEndPointTo(shprossConnectors[2][2].Position);

                Shpross leftDown = shprossPrototype.Copy() as Shpross;
                leftDown.SerialNumber = 0;
                leftDown.MoveStartPointTo(shprossConnectors[2][1].Position);
                leftDown.MoveEndPointTo(shprossConnectors[3][2].Position);

                Shpross downRight = shprossPrototype.Copy() as Shpross;
                downRight.SerialNumber = 0;
                downRight.MoveStartPointTo(shprossConnectors[3][1].Position);
                downRight.MoveEndPointTo(shprossConnectors[0][2].Position);
                shprosses.Add(rightUp);
                shprosses.Add(upLeft);
                shprosses.Add(leftDown);
                shprosses.Add(downRight);
            }
            return shprosses;
        }

        private List<IComponent> WidthAlign(List<ShprossConnector> shprossConnectors, Shpross shprossPrototype, double distance)
        {
            List<IComponent> result = new List<IComponent>();
            double width = distance / 2;

            Angle widthAngle = ModelCalculations.GetAngleBetweenVectors(shprossConnectors[0][1].Primitives[0].GetTangent(0),
                                                                         shprossConnectors[0][2].Primitives[0].GetTangent(0), false);

            double height = Math.Tan(widthAngle.Value / 2) * width;

            shprossConnectors[0].MoveWithOffset(new ModelVector(width, 0));
            shprossConnectors[1].MoveWithOffset(new ModelVector(0, height));
            shprossConnectors[2].MoveWithOffset(new ModelVector(-width, 0));
            shprossConnectors[3].MoveWithOffset(new ModelVector(0, -height));
            result.Add(shprossConnectors[0]);
            result.Add(shprossConnectors[1]);
            result.Add(shprossConnectors[2]);
            result.Add(shprossConnectors[3]);
            result.AddRange(this.GetShprosses(shprossConnectors, shprossPrototype));
            return result;
        }

        private List<IComponent> HeightAlign(List<ShprossConnector> shprossConnectors, Shpross shprossPrototype, double distance)
        {
            List<IComponent> result = new List<IComponent>();
            double height = distance / 2;

            Angle heightAngle = ModelCalculations.GetAngleBetweenVectors(shprossConnectors[1][1].Primitives[0].GetTangent(0),
                                                                         shprossConnectors[1][2].Primitives[0].GetTangent(0), false);

            double width = Math.Tan(heightAngle.Value / 2) * height;

            shprossConnectors[0].MoveWithOffset(new ModelVector(width, 0));
            shprossConnectors[1].MoveWithOffset(new ModelVector(0, height));
            shprossConnectors[2].MoveWithOffset(new ModelVector(-width, 0));
            shprossConnectors[3].MoveWithOffset(new ModelVector(0, -height));
            result.Add(shprossConnectors[0]);
            result.Add(shprossConnectors[1]);
            result.Add(shprossConnectors[2]);
            result.Add(shprossConnectors[3]);
            result.AddRange(this.GetShprosses(shprossConnectors, shprossPrototype));
            return result;

        }

        private List<IComponent> DiamondBorderAlign(List<ShprossConnector> shprossConnectors, Shpross shprossPrototype, double distance)
        {
            List<IComponent> result = new List<IComponent>();
            double hypotenuse = distance;

            Angle widthAngle = ModelCalculations.GetAngleBetweenVectors(shprossConnectors[0][1].Primitives[0].GetTangent(0),
                                                                         shprossConnectors[0][2].Primitives[0].GetTangent(0), false);

            double width = hypotenuse * Math.Cos(widthAngle.Value / 2);
            return this.WidthAlign(shprossConnectors, shprossPrototype, 2 * width);
        }

    }
}
